package com.example.service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.mapper.SysJobLogMapper;
import com.example.model.SysJobLog;
import com.exmaple.dto.RpcRequest;
import com.exmaple.dto.RpcResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@Service
public class SysJobLogServiceImpl extends ServiceImpl<SysJobLogMapper, SysJobLog> implements SysJobLogService, InitializingBean, DisposableBean {

    Logger logger = LoggerFactory.getLogger(getClass());

    private LinkedBlockingQueue<RpcResponse> rpcResponseLinkedBlockingQueue = new LinkedBlockingQueue<>();

    private int corePoolSize = 10;

    private int maximumPoolSize = 20;

    private long keepAliveTime = 5;

    private ThreadPoolExecutor threadPoolExecutor = null;

    private Thread logSaveThread;

    @Override
    public void init() {
        this.threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, new LinkedBlockingDeque());
    }

    @Override
    public void start() {
        this.logSaveThread = new Thread(new Runnable() {
            @Override
            public void run() {
                logger.warn(">>>>>>>>>> logSaveThread started >>>>>>>>>>");
                while (true) {
                    try {
                        RpcResponse rpcResponse = rpcResponseLinkedBlockingQueue.take();
                        threadPoolExecutor.execute(new Runnable() {
                            @Override
                            public void run() {
                                saveRpcResponse(rpcResponse);
                            }
                        });
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        this.logSaveThread.setName("logSaveThread");
        this.logSaveThread.setDaemon(true);
        this.logSaveThread.start();
    }

    @Override
    public void stop() {
        this.threadPoolExecutor.shutdown();
    }

    @Override
    public void addLog(RpcResponse rpcResponse) {
        this.rpcResponseLinkedBlockingQueue.add(rpcResponse);
    }

    @Override
    public void saveRpcResponse(RpcResponse rpcResponse) {
        SysJobLog sysJobLog = new SysJobLog();
        RpcRequest rpcRequest = rpcResponse.getRpcRequest();
        if (rpcRequest != null) {
            sysJobLog.setJobId(rpcRequest.getJobId());
            sysJobLog.setFromId(rpcRequest.getFromId());
            sysJobLog.setTargetId(rpcRequest.getTargetId());
            sysJobLog.setStartTime(new Date(rpcRequest.getStartTime()));
            sysJobLog.setEndTime(new Date(rpcRequest.getEndTime()));
        }
        sysJobLog.setErrorInfo(rpcResponse.getErrInfo());
        sysJobLog.setSuccess(rpcResponse.getSuccess());
        this.save(sysJobLog);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        this.init();
        this.start();
    }

    @Override
    public void destroy() throws Exception {
        this.stop();
    }
}
